
/**
 *	TrueMusic - simple java mp3 player
 *
 *	TrueMusic is free software; you can redistribute it
 *	and/or modify it under the terms of the GNU General
 *	Public License as published by the Free Software
 *	Foundation; either version 2 of the License or (at
 *	your option) any later version.
 *
 *	This program is distributed in the hope that it will be
 *	useful but WITHOUT ANY WARRANTY; without even the
 *	implied warranty of the MERCHANTABILITY or FITNESS FOR
 *	A PARTICULAR PURPOSE. See the GNU General Public
 *	License for more details.
 *
 *	Copyright (c)2005-2007 Ryan Macnak <rmacnak@gmail.com>
 */

package com.servequake.truemusic;


import javazoom.jl.player.advanced.AdvancedPlayer;
import org.farng.mp3.*;

import java.io.*;

/**
 * Audio implemented with the JavaLayer decoder.
 */
public class JavaLayerAudio implements Audio, SeekableAudio, Runnable
{	
	int frames = 0; //number of frames in the clip
	int pos = 0; //the next frame to play
	int current = 0; //the next frame in the decoder
	boolean pause = true;

	Thread runner;
	AdvancedPlayer p; //the mp3 decoder

	String res;
	PlaybackListener l;
	
	public void load(String res, PlaybackListener l) throws Exception
	{
		this.res = res;
		this.l = l;

		//count frames
		p = new AdvancedPlayer( new FileInputStream(res) );
		while(p.skipFrame()) frames++;
		p.close();
		p = null;
	}


	public int getFrames()
	{
		return frames;
	}

/*	public synchronized void play()
	{
		if(runner==null) (runner = new Thread(this)).start();

		if(!pause) pos = 0;
		else
		{
			pause = false;
			notifyAll();
			l.playbackStarted();
		}
	}

	public synchronized void pause()
	{
		if(runner==null) (runner = new Thread(this)).start();

		pause = !pause;
		if(!pause)
		{
			notifyAll();
			l.playbackStarted();
		}
		else l.playbackStopped();
	}

	public synchronized void stop()
	{
		runner = null;

		l.playbackStopped();
		l.frameCompleted(0);
	}
*/
	public synchronized void play()
	{
		//synchronized(pause)
		{
			if(pause && runner!=null) //paused
			{
				pause = false;
				notify();
				l.playbackStarted();
			}
			else if(pause && runner==null) //stopped
			{
				pause = false;
				(runner = new Thread(this)).start();
				l.playbackStarted();
			}
			else if(!pause )//playing
			{
				//synchronized(pos)
				{
					pos = 0;
				}
			}
		}
	}

	public synchronized void pause()
	{
		//synchronized(pause)
		{
			if(pause && runner!=null) //paused
			{
				pause = false;
				notify();
				l.playbackStarted();
			}
			else if(pause && runner==null) //stopped
			{
			}
			else if(!pause )//playing
			{
				pause = true;
				l.playbackStopped();
			}
		}
	}
	
	public synchronized void stop()
	{
		//synchronized(pause)
		{
			if(pause && runner!=null) //paused
			{
				runner = null;
				notify();
			}
			else if(pause && runner==null) //stopped
			{
			}
			else if(!pause )//playing
			{
				pause = true;
				runner = null;
			}
		}
	}
	
	public synchronized void seek(int frame)
	{
		//synchronized(pos)
		{
			this.pos = frame;
		}
	}

				
	public void run()
	{
		try
		{
			while(runner==Thread.currentThread())
			{
				//synchronized(this)
				{
					//while(pause) wait();
					//FIXED JAVA6 ERROR
					while(pause) synchronized(this){wait();}
					
					//synchronized(pos)
					{
						boolean more = playFrame(pos);
						if( more )
						{
							pos++;
							l.frameCompleted(pos);
						}
						else
						{
							runner = null;
							l.playbackCompleted();
						}
					}
				}
				//System.out.println(pos);
			}
			
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		finally
		{
			pos = 0;
			pause = true;
			if(p!=null) p.close();
			p = null;
			runner = null;
		}
	}

	private boolean playFrame(int frame) throws Exception
	{
		if((p==null) || (frame<current))
		{
			p = new AdvancedPlayer( new FileInputStream(res) );
			current = 0;
		}

		while(frame>current)
		{
			if( !p.skipFrame() ) return false;
			current++;
		}

		javazoom.jl.player.JavaSoundAudioDevice.vol.setValue(l.getVolume());
		current++;
		return p.decodeFrame();
	}
	
	public boolean isPlaying(){return !pause;}

	public String getResource(){return res;}
	public String getTitle(){return new File(res).getName();}
	public String getArtist(){return "";}
	public String getAlbum(){return "";}
	public String getTrack(){return "";}
	public String getLyrics(){return "";}
	public String getGenre(){return "";}
	public String toString(){return new File(res).getName();}

	public String formatName(){return "Wav";}
	public String[] getExtensions(){return new String[]{".wav"};}
}
